home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / PowerPlant / CKT AGA 1.0 / LPushButton.cp < prev    next >
Encoding:
Text File  |  1996-05-28  |  7.7 KB  |  374 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        LPushButton.cp
  3.  
  4.     Contains:    AGA-savvy push button class.
  5.  
  6.     Copyright:    ©1996 Chris K. Thomas.  All Rights Reserved.
  7.  
  8.     Version:    1.0
  9. */
  10.  
  11. #include "AGAColors.h"
  12. #include "LPushButton.h"
  13.  
  14. #include <LStream.h>
  15. #include <UMemoryMgr.h>
  16.  
  17. LPushButton*
  18. LPushButton::CreatePushButtonStream(LStream *inStream)
  19. {
  20.     return new LPushButton(inStream);
  21. }
  22.  
  23. LPushButton::LPushButton()
  24. {
  25.     mTitle = ::NewHandle(0);
  26.     ThrowIfMemError_();
  27.     mPressed = false;
  28. }
  29.  
  30.  
  31. LPushButton::LPushButton(LStream *inStream)
  32. :LControl(inStream)
  33. {
  34.     mPressed = false;
  35.     mTitle = NULL;
  36.     
  37.     unsigned char    size;
  38.     
  39.     inStream->ReadData(&size, 1);
  40.     
  41.     mTitle = ::NewHandle(size);
  42.     ThrowIfMemError_();
  43.     
  44.     inStream->ReadData(*mTitle, size);
  45.     
  46.     OptimizeButtonSize();
  47. }
  48.  
  49.  
  50. LPushButton::~LPushButton()
  51. {
  52.     if(mTitle)
  53.         ::DisposeHandle(mTitle);
  54. }
  55.  
  56. //
  57. // OptimizeButtonSize
  58. //
  59. // The AGA specifies 8 pixels between the text
  60. // and the edge of the button, on either side,
  61. // a total height of 20 pixels, and a text baseline
  62. // starting 6 pixels from the bottom.
  63. //
  64.  
  65. void LPushButton::OptimizeButtonSize()
  66. {
  67.     StHandleLocker stlock(mTitle);
  68.     
  69.     UInt16    width = ::TextWidth(*mTitle, 0, GetHandleSize(mTitle));
  70.     UInt16    height = 20;
  71.     
  72.     width += (16 + 2);    //remember that the edge is one pixel on either side
  73.     
  74.     ResizeFrameTo(width, height, false);
  75. }
  76.  
  77. //
  78. // • Imaging ———————————————————————————————————————————————————————————————————————————————————
  79. //
  80.  
  81.  
  82. void
  83. LPushButton::DrawSelf()
  84. {
  85.     Rect    r;
  86.  
  87.     CalcLocalFrameRect(r);
  88.     
  89.     ::InsetRect(&r, -1, -1);
  90.     
  91.     if(IsEnabled())
  92.         DrawOutline(r, &kBlackColor, &kColor12);
  93.     else
  94.         DrawOutline(r, &kColor7, &kColor7);
  95.     
  96.     DrawButtonBackground(r);
  97.     DrawText(r);
  98. }
  99.  
  100. void
  101. LPushButton::DrawText(const Rect &r)
  102. {
  103.     if(!IsPressed())
  104.         RGBForeColor(&kBlackColor);
  105.     else
  106.         RGBForeColor(&kWhiteColor);
  107.  
  108.     UInt16    width = TextWidth(*mTitle, 0, GetHandleSize(mTitle));
  109.     UInt16    textCenter = width/2;
  110.     UInt16    rectCenter = (r.right - r.left)/2;
  111.     
  112.     ::MoveTo(r.left + rectCenter - textCenter, r.bottom - 6);
  113.     ::DrawText(*mTitle, 0, GetHandleSize(mTitle));
  114. }
  115.  
  116. //
  117. // draw the 3D background
  118. //
  119.  
  120. void LPushButton::DrawButtonBackground(const Rect &r)
  121. {
  122.     const RGBColor    *topleftdeepest;
  123.     const RGBColor    *topleftdeeper;
  124.     const RGBColor    *base;
  125.     const RGBColor    *bottomrightdeeper;
  126.     const RGBColor    *bottomrightdeepest;
  127.     Rect        workingRect;
  128.     
  129.     if(IsPressed())
  130.     {
  131.         topleftdeepest = &kColor11;
  132.         topleftdeeper = &kColor10;
  133.         base = &kColor9;
  134.         bottomrightdeeper = &kColor8;
  135.         bottomrightdeepest = &kColor7;
  136.     }
  137.     else
  138.     {
  139.         topleftdeepest = &kColor2;
  140.         topleftdeeper = &kWhiteColor;
  141.         base = &kColor2;
  142.         bottomrightdeeper = &kColor5;
  143.         bottomrightdeepest = &kColor8;
  144.     }
  145.     
  146.     //
  147.     // draw base
  148.     //
  149.     workingRect.left = r.left + 4;
  150.     workingRect.top = r.top + 4;
  151.     workingRect.right = r.right - 3;
  152.     workingRect.bottom = r.bottom - 3;
  153.     
  154.     RGBForeColor(base);
  155.     PaintRect(&workingRect);
  156.     
  157.     //
  158.     // draw first ring (moving inward)
  159.     //
  160.     
  161.     ::RGBForeColor(topleftdeepest);    // left deepest line
  162.     ::MoveTo(r.left + 2, r.top + 3);
  163.     ::LineTo(r.left + 2, r.bottom - 3);
  164.     
  165.     ::MoveTo(r.left + 3, r.top + 2);    // top deepest line    
  166.     ::LineTo(r.right - 3, r.top + 2);
  167.     
  168.     ::RGBForeColor(bottomrightdeepest);    // left deepest line
  169.     
  170.     ::MoveTo(r.right - 2, r.top + 3);    // right deepest line
  171.     ::LineTo(r.right - 2, r.bottom - 3);
  172.     
  173.     ::MoveTo(r.left + 3, r.bottom - 2);    // bottom deepest line    
  174.     ::LineTo(r.right - 3, r.bottom - 2);
  175.     
  176.     //
  177.     // draw second ring (moving inward)
  178.     //
  179.     
  180.     ::RGBForeColor(topleftdeeper);    // left
  181.     ::MoveTo(r.left + 3, r.top + 3);
  182.     ::LineTo(r.left + 3, r.bottom - 3);
  183.     
  184.     ::MoveTo(r.left + 3, r.top + 3);    // top
  185.     ::LineTo(r.right - 3, r.top + 3);
  186.     
  187.     ::RGBForeColor(bottomrightdeeper);
  188.     ::MoveTo(r.right - 3, r.top + 3);    // right
  189.     ::LineTo(r.right - 3, r.bottom - 3);
  190.     
  191.     ::MoveTo(r.left + 3, r.bottom - 3);    // bottom
  192.     ::LineTo(r.right - 3, r.bottom - 3);
  193.     
  194.     //
  195.     // draw corners
  196.     //
  197.     if(IsPressed())
  198.     {
  199.         // top left
  200.         SetCPixel(r.left + 3, r.top + 3, &kColor11);
  201.         SetCPixel(r.left + 4, r.top + 4, &kColor10);
  202.         
  203.         // bottom left
  204.         SetCPixel(r.left + 3, r.bottom - 3, &kColor9);
  205.         SetCPixel(r.left + 3, r.bottom - 2, &kColor10);
  206.         
  207.         // top right
  208.         SetCPixel(r.right - 3, r.top + 3, &kColor9);
  209.         SetCPixel(r.right - 2, r.top + 3, &kColor8);
  210.         
  211.         // bottom right
  212.         SetCPixel(r.right - 3, r.bottom - 3, &kColor7);
  213.         SetCPixel(r.right - 4, r.bottom - 4, &kColor8);
  214.     }
  215.     else
  216.     {
  217.         // top left
  218.         SetCPixel(r.left + 2, r.top + 3, &kColor4);
  219.         SetCPixel(r.left + 3, r.top + 2, &kColor4);
  220.         SetCPixel(r.left + 4, r.top + 4, &kWhiteColor);
  221.         
  222.         
  223.         // bottom left
  224.         SetCPixel(r.left + 2, r.bottom - 3, &kColor4);
  225.         SetCPixel(r.left + 3, r.bottom - 2, &kColor4);
  226.         SetCPixel(r.left + 3, r.bottom - 3, &kColor2);
  227.         
  228.         // top right
  229.         SetCPixel(r.right - 3, r.top + 2, &kColor4);
  230.         SetCPixel(r.right - 2, r.top + 3, &kColor5);
  231.         SetCPixel(r.right - 3, r.top + 3, &kColor2);
  232.         
  233.         // bottom right
  234.         SetCPixel(r.right - 3, r.bottom - 3, &kColor8);
  235.         SetCPixel(r.right - 4, r.bottom - 4, &kColor5);
  236.     }
  237. }
  238.  
  239. //
  240. // draw the button outline
  241. //
  242.  
  243. void LPushButton::DrawOutline(    const Rect &r,
  244.                                 const RGBColor *inOutlineColor,
  245.                                 const RGBColor *inOutlineAliasColor)
  246. {
  247.     RGBForeColor(inOutlineColor);    // left side
  248.     MoveTo(r.left + 1, r.top + 4);
  249.     LineTo(r.left + 1, r.bottom - 4);
  250.     
  251.     MoveTo(r.right - 1, r.top + 4);        // right side
  252.     LineTo(r.right - 1, r.bottom - 4);
  253.     
  254.     MoveTo(r.left + 4, r.top + 1);        // top
  255.     LineTo(r.right - 4, r.top + 1);
  256.     
  257.     MoveTo(r.left + 4, r.bottom - 1);    // bottom
  258.     LineTo(r.right - 4, r.bottom - 1);
  259.     
  260.     //
  261.     // corners  ••• setcpixel isn’t very efficient
  262.     //
  263.     
  264.     SetCPixel(r.left + 3, r.top + 1, inOutlineAliasColor);    // top, left corner
  265.     SetCPixel(r.left + 2, r.top + 2, inOutlineColor);
  266.     SetCPixel(r.left + 1, r.top + 3, &kColor12);
  267.     
  268.     SetCPixel(r.left + 3, r.bottom - 1, inOutlineAliasColor);    // bottom, left corner
  269.     SetCPixel(r.left + 2, r.bottom - 2, inOutlineColor);
  270.     SetCPixel(r.left + 1, r.bottom - 3, &kColor12);
  271.     
  272.     SetCPixel(r.right - 3, r.top + 1, inOutlineAliasColor);    // top, right corner
  273.     SetCPixel(r.right - 2, r.top + 2, inOutlineColor);
  274.     SetCPixel(r.right - 1, r.top + 3, inOutlineAliasColor);
  275.     
  276.     SetCPixel(r.right - 3, r.bottom - 1, inOutlineAliasColor);    // bottom, right corner
  277.     SetCPixel(r.right - 2, r.bottom - 2, inOutlineColor);
  278.     SetCPixel(r.right - 1, r.bottom - 3, inOutlineAliasColor);
  279. }
  280.  
  281. //
  282. // • Mouse handling ————————————————————————————————————————————————————————————————————————————
  283. //
  284.  
  285. void LPushButton::HotSpotAction(Int16 /*inHotSpot*/, Boolean inCurrInside, Boolean inPrevInside)
  286. {
  287.     if(inPrevInside == false)
  288.     {
  289.         //
  290.         // previously outside the button
  291.         // currently inside the button
  292.         //
  293.         if(inCurrInside == true)
  294.         {
  295.             mPressed = true;
  296.             
  297.             Rect r;
  298.             
  299.             CalcLocalFrameRect(r);
  300.             InsetRect(&r, -1, -1);
  301.             
  302.             DrawButtonBackground(r);
  303.             DrawText(r);
  304.         }
  305.     }
  306.     else
  307.     {
  308.         if(inCurrInside == false)
  309.         {
  310.             //
  311.             // previously inside
  312.             // currently outside
  313.             //
  314.             
  315.             mPressed = false;
  316.             
  317.             Rect r;
  318.             
  319.             CalcLocalFrameRect(r);
  320.             InsetRect(&r, -1, -1);
  321.             
  322.             DrawButtonBackground(r);
  323.             DrawText(r);
  324.         }
  325.     }
  326. }
  327.  
  328.  
  329. void
  330. LPushButton::HotSpotResult(Int16 /*inHotSpot*/)
  331. {
  332.     if(mPressed)
  333.     {
  334.         mPressed = false;
  335.         
  336.         Rect r;
  337.         CalcLocalFrameRect(r);
  338.         InsetRect(&r, -1, -1);
  339.         
  340.         DrawButtonBackground(r);
  341.         DrawText(r);
  342.     }
  343.     
  344.     BroadcastValueMessage();
  345. }
  346.  
  347. //
  348. // • Title Accesors ————————————————————————————————————————————————————————————————————————————
  349. //
  350.  
  351. StringPtr
  352. LPushButton::GetDescriptor(Str255 outDescriptor) const
  353. {
  354.     StHandleLocker stlock(mTitle);
  355.  
  356.     outDescriptor[0] = GetHandleSize(mTitle);
  357.     BlockMoveData(*mTitle, &outDescriptor[1], outDescriptor[0]);
  358.     
  359.     return NULL;    //this is bad, but I'm not going to waste 255 bytes per button - what was GHD thinking??
  360. }
  361.  
  362. void
  363. LPushButton::SetDescriptor(ConstStringPtr inDescriptor)
  364. {
  365.     SetHandleSize(mTitle, inDescriptor[0]);
  366.     ThrowIfMemError_();
  367.  
  368.     StHandleLocker stlock(mTitle);
  369.  
  370.     BlockMoveData(&inDescriptor[1], *mTitle, inDescriptor[0]);
  371.     
  372.     OptimizeButtonSize();
  373. }
  374.